﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace WindowsAPI
{
    /// <summary> This class allows you to manage a hotkey </summary>
    public class GlobalHotkeys : IDisposable
    {
        public enum MODKey
        {
            Alt = 1,
            Control = 2,
            Shift = 4,
            WIN = 8
        }

        //public const int WM_HOTKEY = 0x312;

        public GlobalHotkeys()
        {
            using(var process = Process.GetCurrentProcess())
                Handle = process.Handle;
        }

        /// <summary> handle of the current process </summary>
        public IntPtr Handle { get; private set; }

        /// <summary> the ID for the hotkey </summary>
        public short HotkeyID { get; private set; }

        /// <summary> register the hotkey </summary>
        public void RegisterGlobalHotKey(int hotkey, int modifiers, IntPtr handle)
        {
            UnregisterGlobalHotKey();
            Handle = handle;
            RegisterGlobalHotKey(hotkey, modifiers);
        }

        /// <summary> register the hotkey </summary>
        public void RegisterGlobalHotKey(int hotkey, int modifiers)
        {
            UnregisterGlobalHotKey();

            try
            {
                // use the GlobalAddAtom API to get a unique ID (as suggested by MSDN docs)
                var lv_AtomName = Thread.CurrentThread.ManagedThreadId.ToString("X8") +
                    GetType().FullName;
                HotkeyID = Kernel32.GlobalAddAtom(lv_AtomName);
                if(HotkeyID == 0)
                    throw new Exception(string.Format("Unable to generate unique hotkey ID. Error: {0}", Marshal.GetLastWin32Error()));

                // register the hotkey, throw if any error
                if(!User32.RegisterHotKey(Handle, HotkeyID, modifiers, hotkey))
                    throw new Exception(string.Format("Unable to register hotkey. Error: {0}", Marshal.GetLastWin32Error()));

            }
            catch(Exception e)
            {
                // clean up if hotkey registration failed
                UnregisterGlobalHotKey();
                Console.WriteLine(e);
            }
        }

        /// <summary> unregister the hotkey </summary>
        public void UnregisterGlobalHotKey()
        {
            if(HotkeyID == 0) return;
            User32.UnregisterHotKey(Handle, HotkeyID);
            // clean up the atom list
            Kernel32.GlobalDeleteAtom(HotkeyID);
            HotkeyID = 0;
        }

        public void Dispose() { UnregisterGlobalHotKey(); }
    }
}

//GlobalHotkeys hotkey;


//hotkey = new GlobalHotkeys();
//hotkey.RegisterGlobalHotKey( (int) Keys.F11, GlobalHotkeys.MOD_CONTROL );
//hotkey.UnregisterGlobalHotKey();